home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / sound / rsynth22.zip / SAY.C < prev    next >
Text File  |  1996-09-13  |  10KB  |  464 lines

  1. #include <config.h>
  2. /* $Id: say.c,v 1.13 1994/11/08 13:30:50 a904209 Exp a904209 $
  3.    $Log: say.c,v $
  4.  * Revision 1.13  1994/11/08  13:30:50  a904209
  5.  * 2.0 release
  6.  *
  7.  * Revision 1.12  1994/11/04  13:32:31  a904209
  8.  * 1.99.1 - Change configure stuff
  9.  *
  10.  * Revision 1.11  1994/11/02  10:55:31  a904209
  11.  * Add autoconf. Tested on SunOS/Solaris
  12.  *
  13.  * Revision 1.10  1994/10/04  17:12:50  a904209
  14.  * 3rd pre-release
  15.  *
  16.  * Revision 1.9  1994/10/04  09:08:27  a904209
  17.  * Next Patch merge
  18.  *
  19.  * Revision 1.8  1994/10/03  08:41:47  a904209
  20.  * 2nd pre-release                                                         
  21.  *
  22.  * Revision 1.7  1994/09/19  15:48:29  a904209
  23.  * Split hplay.c, gdbm dictionary, start of f0 contour, netaudio and HP ports
  24.  *
  25.  * Revision 1.6  1994/04/15  16:47:37  a904209
  26.  * Edits for Solaris2.3 (aka SunOs 5.3)
  27.  *
  28.  * Revision 1.5  1994/02/24  15:03:05  a904209
  29.  * Added contributed linux, NeXT and SGI ports.
  30.  *
  31.  * Revision 1.4  93/11/18  16:29:06  a904209
  32.  * Migrated nsyth.c towards Jon's scheme - merge still incomplete
  33.  * 
  34.  * Revision 1.3  93/11/16  14:32:44  a904209
  35.  * Added RCS Ids, partial merge of Jon's new klatt/parwave
  36.  *
  37.  * Revision 1.3  93/11/16  14:00:58  a904209
  38.  * Add IDs and merge Jon's klatt sources - incomplete
  39.  *
  40.  */
  41. char *say_id = "$Id: say.c,v 1.13 1994/11/08 13:30:50 a904209 Exp a904209 $";
  42. extern char *Revision;
  43. #include <stdio.h>
  44. #include <ctype.h>
  45. #include <useconfig.h>
  46. #include <math.h>
  47. #include <signal.h>
  48. #include <setjmp.h>
  49. #include <float.h>
  50. #include "proto.h"
  51. #include "nsynth.h"
  52. #include "hplay.h"
  53. #include "dict.h"
  54. #include "ASCII.h"
  55. #include "darray.h"
  56. #include "holmes.h"
  57. #include "phtoelm.h"
  58. #include "text.h"
  59. #include "getargs.h"
  60. #include "phones.h"
  61. #include "file.h"
  62. #include "say.h"
  63.  
  64. char *program = "say";
  65.  
  66. static int verbose = 0;
  67.  
  68. jmp_buf mark;
  69.  
  70. unsigned
  71. spell_out(word, n, phone)
  72. char *word;
  73. int n;
  74. darray_ptr phone;
  75. {
  76.  unsigned nph = 0;
  77. /* fprintf(stderr, "Spelling '%.*s'\n", n, word); */
  78.  while (n-- > 0)
  79.   {
  80.    nph += xlate_string(ASCII[*word++ & 0x7F], phone);
  81.   }
  82.  return nph;
  83. }
  84.  
  85. int
  86. suspect_word(s, n)
  87. char *s;
  88. int n;
  89. {
  90.  int i = 0;
  91.  int seen_lower = 0;
  92.  int seen_upper = 0;
  93.  int seen_vowel = 0;
  94.  int last = 0;
  95.  for (i = 0; i < n; i++)
  96.   {
  97.    char ch = *s++;
  98.    if (i && last != '-' && isupper(ch))
  99.     seen_upper = 1;
  100.    if (islower(ch))
  101.     {
  102.      seen_lower = 1;
  103.      ch = toupper(ch);
  104.     }
  105.    if (ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U' || ch == 'Y')
  106.     seen_vowel = 1;
  107.    last = ch;
  108.   }
  109.  return !seen_vowel || (seen_upper && seen_lower) || !seen_lower;
  110. }
  111.  
  112. static unsigned xlate_word PROTO((char *word, int n, darray_ptr phone));
  113.  
  114. static unsigned
  115. xlate_word(word, n, phone)
  116. char *word;
  117. int n;
  118. darray_ptr phone;
  119. {
  120.  unsigned nph = 0;
  121.  if (*word != '[')
  122.   {
  123.    if (dict)
  124.     {
  125.      unsigned char *p = dict_find(word, n);
  126.      if (p)
  127.       {
  128.        unsigned char *s = p;
  129.        while (*s)
  130.         {
  131.          char *x = dialect[(unsigned) (*s++)];
  132.          while (*x)
  133.           {
  134.            phone_append(phone, *x++);
  135.            nph++;
  136.           }
  137.         }
  138.        phone_append(phone, ' ');
  139.        free(p);
  140.        return nph + 1;
  141.       }
  142.      else
  143.       {
  144.        /* If supposed word contains '.' or '-' try breaking it up... */
  145.        char *h = word;
  146.        while (h < word + n)
  147.         {
  148.          if (*h == '.' || *h == '-')
  149.           {
  150.            nph += xlate_word(word, h++ - word, phone);
  151.            nph += xlate_word(h, word + n - h, phone);
  152.            return nph;
  153.           }
  154.          else
  155.           h++;
  156.         }
  157.       }
  158.     }
  159.    if (suspect_word(word, n))
  160.     {
  161.       nph = spell_out(word, n, phone);
  162.       return(nph);
  163.     }
  164.    else
  165.     {
  166.      if (dict || verbose)
  167.       /* fprintf(stderr, "Guess %p '%.*s'\n", dict, n, word) */; 
  168.      nph += NRL(word, n, phone);
  169.     }
  170.   }
  171.  else
  172.   {
  173.    if ((++word)[(--n) - 1] == ']')
  174.     n--;
  175.    while (n-- > 0)
  176.     {
  177.      phone_append(phone, *word++);
  178.      nph++;
  179.     }
  180.   }
  181.  phone_append(phone, ' ');
  182.  return nph + 1;
  183. }
  184.  
  185. void
  186. say_phones(phone, len, verbose)
  187. char *phone;
  188. int len;
  189. int verbose;
  190. {
  191.  darray_t elm;
  192.  unsigned frames;
  193.  darray_init(&elm, sizeof(char), len);
  194.  if ((frames = phone_to_elm(phone, len, &elm)))
  195.   {
  196.    unsigned max_samples = frames * klatt_global.nspfr;
  197.    short *samp = (short *) malloc(sizeof(short) * max_samples);
  198.    if (verbose)
  199.     fprintf(stderr,"%.*s\n", len, phone);
  200.    if (samp)
  201.     {
  202.      unsigned nsamp;
  203.  
  204.      nsamp = holmes(elm.items, (unsigned char *) darray_find(&elm, 0),
  205.                              max_samples, samp);
  206.      audio_play(nsamp, samp);
  207.      if (file_write)
  208.       (*file_write)(nsamp, samp);
  209.      free(samp);
  210.     }
  211.   }
  212.  darray_free(&elm);
  213. }
  214.  
  215.  
  216.  
  217.  
  218. unsigned
  219. xlate_string(string, phone)
  220. char *string;
  221. darray_ptr phone;
  222. {
  223.  unsigned nph = 0;
  224.  char *s = string;
  225.  char ch;
  226.  while (isspace(ch = *s))
  227.   s++;
  228.  while ((ch = *s))
  229.   {
  230.    char *word = s;
  231.    if (isalpha(ch))
  232.     {
  233.      while (isalpha(ch = *s) || ((ch == '\'' || ch == '-' || ch == '.') && isalpha(s[1])))
  234.       s++;
  235.      if (!ch || isspace(ch) || ispunct(ch) || (isdigit(ch) && !suspect_word(word, s - word)))
  236.       {
  237.       nph += xlate_word(word, s - word, phone);
  238.       }
  239.      else
  240.       {
  241.        while ((ch = *s) && !isspace(ch) && !ispunct(ch))
  242.         s++;
  243.        nph += spell_out(word, s - word, phone);
  244.       }
  245.     }
  246.    else if (isdigit(ch) || (ch == '-' && isdigit(s[1])))
  247.     {
  248.      int sign = (ch == '-') ? -1 : 1;
  249.      long value = 0;
  250.      if (sign < 0)
  251.       ch = *++s;
  252.      while (isdigit(ch = *s))
  253.       {
  254.        value = value * 10 + ch - '0';
  255.        s++;
  256.       }
  257.      if (ch == '.' && isdigit(s[1]))
  258.       {
  259.        word = ++s;
  260.        nph += xlate_cardinal(value * sign, phone);
  261.        nph += xlate_string("point", phone);
  262.        while (isdigit(ch = *s))
  263.         s++;
  264.        nph += spell_out(word, s - word, phone);
  265.       }
  266.      else
  267.       {
  268.        /* check for ordinals, date, time etc. can go in here */
  269.        nph += xlate_cardinal(value * sign, phone);
  270.       }
  271.     }
  272.    else if (ch == '[' && strchr(s, ']'))
  273.     {
  274.      char *word = s;
  275.      while (*s && *s++ != ']')
  276.       /* nothing */ ;
  277.      nph += xlate_word(word, s - word, phone);
  278.     }
  279.    else if (ispunct(ch))
  280.     {
  281.      switch (ch)
  282.       {
  283.         /* On end of sentence flush the buffer ... */
  284.        case '!':
  285.        case '?':
  286.        case '.':
  287.         if ((!s[1] || isspace(s[1])) && phone->items)
  288.          {
  289.           say_phones((char *) darray_find(phone, 0), phone->items, verbose);
  290.           phone->items = 0;
  291.          }
  292.         s++;
  293.         phone_append(phone, ' ');
  294.         break;
  295.        case '"':                 /* change pitch ? */
  296.        case ':':
  297.        case '-':
  298.        case ';':
  299.        case ',':
  300.        case '(':
  301.        case ')':
  302.         s++;
  303.         phone_append(phone, ' ');
  304.         break;
  305.        case '[':
  306.         {
  307.          char *e = strchr(s, ']');
  308.          if (e)
  309.           {
  310.            s++;
  311.            while (s < e)
  312.             phone_append(phone, *s++);
  313.            s = e + 1;
  314.            break;
  315.           }
  316.         }
  317.        default:
  318.         nph += spell_out(word, 1, phone);
  319.         s++;
  320.         break;
  321.       }
  322.     }
  323.    else
  324.     {
  325.      while ((ch = *s) && !isspace(ch))
  326.       s++;
  327.      nph += spell_out(word, s - word, phone);
  328.     }
  329.    while (isspace(ch = *s))
  330.     s++;
  331.   }
  332.  return nph;
  333. }
  334.  
  335. char *
  336. concat_args(argc, argv)
  337. int argc;
  338. char *argv[];
  339. {
  340.  int len = 0;
  341.  int i;
  342.  char *buf;
  343.  for (i = 1; i < argc; i++)
  344.   len += strlen(argv[i]) + 1;
  345.  buf = (char *) malloc(len);
  346.  if (buf)
  347.   {
  348.    char *d = buf;
  349.    for (i = 1; i < argc;)
  350.     {
  351.      char *s = argv[i++];
  352.      while (*s)
  353.       *d++ = *s++;
  354.      if (i < argc)
  355.       *d++ = ' ';
  356.      else
  357.       *d = '\0';
  358.     }
  359.   }
  360.  return buf;
  361. }
  362.  
  363. void
  364. say_string(s)
  365. char *s;
  366. {
  367.  darray_t phone;
  368.  darray_init(&phone, sizeof(char), 128);
  369.  xlate_string(s, &phone);
  370.  if (phone.items)
  371.   say_phones((char *) darray_find(&phone, 0), phone.items, verbose);
  372.